package memory

import (
	"github.com/sirupsen/logrus"
	"github.com/ingopansa/userinfoservice/storage"
	"sync"
	"fmt"
	"github.com/ingopansa/userinfoservice/model"
	"github.com/pkg/errors"
)

type Config struct {
	// The in memory implementation has no config.
}

type memStorage struct {
	mu sync.Mutex

	//clients         map[string]storage.Client
	users	map[string]model.User

	keys storage.Keys
	logger logrus.FieldLogger
}

// New returns an in memory storage.
func New(logger logrus.FieldLogger) storage.Storage {
	return &memStorage{
		users:		make(map[string]model.User),
		logger:     logger,
	}
}

// Open always returns a new in memory storage.
func (c *Config) Open(logger logrus.FieldLogger) (storage.Storage, error) {
	return New(logger), nil
}




func (s *memStorage) tx(f func()) {
	s.mu.Lock()
	defer s.mu.Unlock()
	f()
}

func (s *memStorage) Close() error { return nil }


func (s *memStorage) GetKeys() (keys storage.Keys, err error) {
	s.tx(func() { keys = s.keys })
	return
}

func (s *memStorage) UpdateKeys(updater func(old storage.Keys) (storage.Keys, error)) (err error) {
	s.tx(func() {
		var keys storage.Keys
		if keys, err = updater(s.keys); err == nil {
			s.keys = keys
		}
	})
	return
}

func (s *memStorage) ListUsers()(users []model.User, err error){
	fmt.Println("memory.ListUsers()")
	s.tx(func() {
		for _, c := range s.users {
			users = append(users, c)
		}
	})
	return
}

func (s *memStorage) GetUser(ID string)(user model.User, err error){
	s.tx(func(){
		user = s.users[ID]
	})

	return
}

func (s *memStorage) AddUser(user model.User)(err error){
	return errors.New("not implemented")
}